package com.marvels.financial.loan.service.impl;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import com.marvels.common.constants.MarvelsConstant;
import com.marvels.common.constants.RedisKeyConstant;
import com.marvels.common.utils.CacheUtils;
import com.marvels.common.utils.CommonProperties;
import com.marvels.common.utils.GenerateReqNoUtils;
import com.marvels.common.utils.MarvelsLogUtil;
import com.marvels.common.utils.ServerProperties;
import com.marvels.financial.loan.dao.McfeCustomerLoanContractDao;
import com.marvels.financial.loan.dao.McfePaymentWithholdDao;
import com.marvels.financial.loan.dao.McfePaymentWithholdDetailDao;
import com.marvels.financial.loan.dao.McfeRepaymentFlowDao;
import com.marvels.financial.loan.dto.HandWithholdConditionDTO;
import com.marvels.financial.loan.dto.HandleWithholePaymentDTO;
import com.marvels.financial.loan.dto.McfeCustomerLoanContractDTO;
import com.marvels.financial.loan.dto.McfePaymentWithholdDTO;
import com.marvels.financial.loan.dto.McfePaymentWithholdDetailDTO;
import com.marvels.financial.loan.dto.McfeRepaymentFlowDTO;
import com.marvels.financial.loan.dto.PaymentResponse;
import com.marvels.financial.loan.service.TimingWithholdTaskTaskletApi;
import com.marvels.financial.loan.service.WithholdPaymentApi;

import net.sf.json.JSONObject;

@Service
public class TimingWithholdTaskTaskletImpl implements TimingWithholdTaskTaskletApi {

	@Autowired
	private McfePaymentWithholdDetailDao detailDao;

	@Autowired
	private McfeRepaymentFlowDao flowDao;

	@Autowired
	private WithholdPaymentApi withholdPaymentApi;

	@Autowired
	private McfePaymentWithholdDao withholdDao;

	@Autowired
	private McfeCustomerLoanContractDao contractDao;
	
	@Value("${config.properties.path}")
	private  String configPropertiesPath;

	@Override
	public void timingWithhold() {
		MarvelsLogUtil.getInstance().info(">>>>>>>>>>定时代扣还款计划开始");
		if (!"on".equalsIgnoreCase(CommonProperties.getTimingWithholdPayment())) {
			MarvelsLogUtil.getInstance().info(">>>>>>>>>>定时代扣还款计划开关关闭");
			return;
		}
		String batchName = Thread.currentThread().getId() + "-" + UUID.randomUUID().toString().replace("-", "");
		
		// 先插入代扣总记录
		int count = 0;
		
		// 依据配置决定扣款金额
		// 当配置为Y时，放款T+1日开始扣款，在无展期情况下每日扣款金额为150元，扣7天。任意一日未扣取到则将其金额进行累加到下一扣款日中
		//           如果做了展期则扣款日减一天
		if(StringUtils.equalsIgnoreCase("Y", CommonProperties.getNewRepaymentFlag())) {
			count = withholdDao.newInsertWithholdByBatch(batchName);
		}else {
			count = withholdDao.insertWithholdByBatch(batchName);
		}
		
		if (count < 1) {
			MarvelsLogUtil.getInstance().info(">>>>>>>>>>没有需要代扣的还款计划");
			return;
		}
		
		sendRepayment(batchName);
	}
	
	/**
	 * 依据待扣款批次号正式发起扣款
	 * @param batchName
	 */
	private void sendRepayment(String batchName) {
		List<McfePaymentWithholdDTO> withholdList = withholdDao.selectByBatchName(batchName);
		for (McfePaymentWithholdDTO withholdDTO : withholdList) {
			String loanId = withholdDTO.getLoanId();
			// 加锁 避免重复插入数据
			String key = RedisKeyConstant.HAND_PAYMENT_WITHHOLD + loanId;
			boolean isNotLock = false;
			try {
				isNotLock = CacheUtils.isNotLock(key, loanId);
				if (isNotLock) {
					// 先将这个key设置过期时间
					CacheUtils.setExpire(key, 300);
					HandWithholdConditionDTO conditionDTO = new HandWithholdConditionDTO();
					conditionDTO.setLoanId(loanId);
					BigDecimal succcessAmount = new BigDecimal("0.00");
					BigDecimal withholdAmount = new BigDecimal("0.00");
					// 查询需要代扣的还款计划
					String reqNoBatch = GenerateReqNoUtils.transctionReq("TX");
					// 判断还款计划对应的进件是否有处在交易中的代扣
					McfePaymentWithholdDetailDTO detailDTO = detailDao.selectTradingByLoanId(loanId);
					if (detailDTO != null) {
						MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在交易中的代扣");
						McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
						withholdDTOUpdate.setStatus("9");// 将代扣流水状修改成失败
						withholdDTOUpdate.setUpdatedBy("SYSTEM");
						withholdDTOUpdate.setUpdatedDate(new Date());
						withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
						continue;
					}

					// 判断还款计划对应的进件是否有处在正在冲账中的流水
					McfeRepaymentFlowDTO flowDTO = flowDao.selectDealingByLoanId(loanId);
					if (flowDTO != null) {
						MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",有处在冲账中或未冲账的流水");
						McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
						withholdDTOUpdate.setStatus("9");// 将代扣流水状修改成失败
						withholdDTOUpdate.setUpdatedBy("SYSTEM");
						withholdDTOUpdate.setUpdatedDate(new Date());
						withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
						continue;
					}

					// 查询合同状态
					McfeCustomerLoanContractDTO contractDTO = contractDao.selectContractByLoanId(loanId);
					if (!"0".equals(String.valueOf(contractDTO.getStatus()))
							&& !"1".equals(String.valueOf(contractDTO.getStatus()))) {
						MarvelsLogUtil.getInstance().info(">>>>>>>>>>loanId:" + loanId + ",合同状态不处于还款中");
						McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
						withholdDTOUpdate.setStatus("9");// 0 状态初始化 、1 代扣成功 ，2
															// 代扣中，9 代扣失败，10 退款
						withholdDTOUpdate.setUpdatedBy("SYSTEM");
						withholdDTOUpdate.setUpdatedDate(new Date());
						withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
						continue;
					}
					//同步合同信息
					//withholdPaymentApi.synchronizedBankCard(contractDTO, null);
					String paymentChannel = ServerProperties.getValue(configPropertiesPath, "common.properties", "payment_channel");
					withholdAmount = withholdDTO.getAmount();
					if (withholdAmount.compareTo(BigDecimal.ZERO) < 1) {
						MarvelsLogUtil.getInstance()
								.info(">>>>>>>>>>自动代扣结束，loanId:" + loanId + ",应还金额:" + withholdAmount + ",小于等于0");
						McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
						withholdDTOUpdate.setStatus("9");
						withholdDTOUpdate.setUpdatedBy("SYSTEM");
						withholdDTOUpdate.setUpdatedDate(new Date());
						withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
						continue;
					}
					// 拆分金额
//					BigDecimal[] splitAmount = withholdApi.amountSplit(withholdAmount,
//							contractDTO.getPaymentBankHead());
//					if (null == splitAmount || splitAmount.length < 1) {
//						splitAmount = new BigDecimal[] { withholdAmount };
//					}
					// 去掉金额拆分,简版不会超限额
					BigDecimal[] splitAmount = new BigDecimal[] { withholdAmount };
					// 将金额循环支付
					for (int i = 0; i < splitAmount.length; i++) {
						// 持久化代扣流水
						String reqNo = GenerateReqNoUtils.transctionReq("TX");
						detailDTO = new McfePaymentWithholdDetailDTO();
						detailDTO.setReqChannel(paymentChannel);
						detailDTO.setAmount(splitAmount[i]);
						detailDTO.setBankCardNo(withholdDTO.getBankCardNo());
						detailDTO.setBankHeadLink(withholdDTO.getBankHeadLink());
						detailDTO.setBankName(withholdDTO.getBankName());
						detailDTO.setChannelCode(contractDTO.getChannelCode());
						detailDTO.setChannelName(contractDTO.getChannelName());
						detailDTO.setCreatedBy("SYSTEM");
						detailDTO.setCreatedDate(new Date());
						detailDTO.setCustCardNo(contractDTO.getCustCardNo());
						detailDTO.setCustName(contractDTO.getCustName());
						detailDTO.setFundCode(contractDTO.getFundCode());
						detailDTO.setFundName(contractDTO.getFundName());
						detailDTO.setLoanId(contractDTO.getLoanId());
						detailDTO.setMobile(contractDTO.getMobile());
						detailDTO.setPayType("1");
						detailDTO.setProductCode(contractDTO.getProductCode());
						detailDTO.setProductName(contractDTO.getProductName());
						detailDTO.setProductType(contractDTO.getProductType());
						detailDTO.setProductTypeName(contractDTO.getProductTypeName());
						detailDTO.setStatus("1");// 交易中
						detailDTO.setTranctionDate(new Date());
						detailDTO.setTransctionSeq(reqNo);
						detailDTO.setUpdatedBy("SYSTEM");
						detailDTO.setUpdatedDate(new Date());
						detailDTO.setWithholdCode(reqNoBatch);
						int detailCount = detailDao.insertSelective(detailDTO);
						if (detailCount < 1) {
							McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
							withholdDTOUpdate.setStatus("0");
							withholdDTOUpdate.setUpdatedBy("SYSTEM");
							withholdDTOUpdate.setUpdatedDate(new Date());
							withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
							continue;
						}
						
						// 发起代扣
						HandleWithholePaymentDTO paymentDTO = new HandleWithholePaymentDTO();
						paymentDTO.setAmount(splitAmount[i]);
						paymentDTO.setBankName(contractDTO.getPaymentBankName());
						paymentDTO.setCustBankAccountNo(contractDTO.getPaymentAcctNo());
						paymentDTO.setCustBankAcctType("1");
						paymentDTO.setCustBindPhoneNo(contractDTO.getMobile());
						paymentDTO.setCustId(contractDTO.getCustCardNo());
						paymentDTO.setCustName(contractDTO.getCustName());
						paymentDTO.setFundSource(contractDTO.getFundCode());
						paymentDTO.setLoanId(contractDTO.getLoanId());
						paymentDTO.setMerchantTreatyNo(contractDTO.getLoanId());
						paymentDTO.setRemark("自动代扣");
						paymentDTO.setReqNo(reqNo);
						PaymentResponse paymentResponse = null;
						MarvelsLogUtil.getInstance()
								.info(">>>>>>>>自动代扣发起代扣交易请求参数:" + JSONObject.fromObject(paymentDTO));
						try {
							paymentResponse = withholdPaymentApi.withholdPayment(paymentDTO);
						} catch (Exception e) {
							MarvelsLogUtil.getInstance().error(">>>>>>>>自动代扣发起代扣交易异常:", e);
						}
						MarvelsLogUtil.getInstance()
								.info(">>>>>>>>自动代扣发起代扣交易返回参数:" + JSONObject.fromObject(paymentResponse));
						String status = "";// ；1交易中; 2代扣成功 9代扣失败
						String rtnOrderNo = "";// 第三方返回订单号
						String rtnResponseCode = "";// 扣款返回码
						String rtnResponseMsg = "";// 扣款返回信息
						BigDecimal amountAct = new BigDecimal("0");// 实际成功金额
						if (null == paymentResponse) {
							status = "1";
							rtnResponseMsg = "返回信息为空";
						} else {
							rtnResponseMsg = paymentResponse.getMsg();
							rtnOrderNo = paymentResponse.getOrderNumber();
							rtnResponseCode = paymentResponse.getCode();
							if ("0".equals(paymentResponse.getCode())) {// 成功
								status = "2";
								amountAct = splitAmount[i];
								succcessAmount = succcessAmount.add(amountAct);
							}else if(MarvelsConstant.FAILED.equals(paymentResponse.getCode())){//失败
								status = "9";
							}else{// 其余做处理中处理
								status = "1";
							}
						}
						// 更新代扣流水
						McfePaymentWithholdDetailDTO detailDTOUpdate = new McfePaymentWithholdDetailDTO();
						detailDTOUpdate.setId(detailDTO.getId());
						detailDTOUpdate.setUpdatedBy("SYSTEM");
						detailDTOUpdate.setUpdatedDate(new Date());
						detailDTOUpdate.setAmountAct(amountAct);
						detailDTOUpdate.setStatus(status);// ；1交易中; 2代扣成功 9代扣失败
						detailDTOUpdate.setRtnOrderNo(rtnOrderNo);
						// 001 快付通（云科贷） ,002 宝付（云科贷） 003 宝付（口袋） 004 宝付（渤海） 005
						// 支付宝
						// 006 运营
						
						detailDTOUpdate.setResChannel(paymentChannel);
						detailDTOUpdate.setRtnResponseDate(new Date());
						detailDTOUpdate.setRtnResponseCode(rtnResponseCode);// 扣款返回码
						detailDTOUpdate.setRtnResponseMsg(rtnResponseMsg);// 扣款返回信息
						detailDao.updateByPrimaryKeySelective(detailDTOUpdate);
						if ("2".equals(status)) {// 成功
							// 持久化还款流水/冲销流水
							McfeRepaymentFlowDTO mcfeRepaymentFlowDto = new McfeRepaymentFlowDTO();
							mcfeRepaymentFlowDto.setAmountAct(amountAct);
							mcfeRepaymentFlowDto.setCustName(contractDTO.getCustName());
							mcfeRepaymentFlowDto.setCustCardNo(contractDTO.getCustCardNo());
							mcfeRepaymentFlowDto.setStatus("0");
							mcfeRepaymentFlowDto.setLoanId(contractDTO.getLoanId());
							mcfeRepaymentFlowDto.setBankCardNo(contractDTO.getPaymentAcctNo());
							mcfeRepaymentFlowDto.setBankName(contractDTO.getPaymentBankName());
							mcfeRepaymentFlowDto.setBankHeadLink(contractDTO.getPaymentBankHead());
							mcfeRepaymentFlowDto.setFundCode(contractDTO.getFundCode());
							mcfeRepaymentFlowDto.setFundName(contractDTO.getFundName());
							mcfeRepaymentFlowDto.setProductType(contractDTO.getProductType());
							mcfeRepaymentFlowDto.setProductTypeName(contractDTO.getProductTypeName());
							mcfeRepaymentFlowDto.setProductCode(contractDTO.getProductCode());
							mcfeRepaymentFlowDto.setProductName(contractDTO.getProductName());
							mcfeRepaymentFlowDto.setChannelCode(contractDTO.getChannelCode());
							mcfeRepaymentFlowDto.setChannelName(contractDTO.getChannelName());
							mcfeRepaymentFlowDto.setCreatedBy("SYSTEM");
							mcfeRepaymentFlowDto.setUpdatedBy("SYSTEM");
							mcfeRepaymentFlowDto.setCreatedDate(new Date());
							mcfeRepaymentFlowDto.setUpdatedDate(new Date());
							mcfeRepaymentFlowDto.setMobile(contractDTO.getMobile());
							mcfeRepaymentFlowDto.setRepayStyle("1");
							mcfeRepaymentFlowDto.setResChannel(paymentChannel);
							mcfeRepaymentFlowDto.setRtnOrderNo(rtnOrderNo);
							mcfeRepaymentFlowDto.setRtnResponseCode(rtnResponseCode);
							mcfeRepaymentFlowDto.setRtnResponseDate(new Date());
							mcfeRepaymentFlowDto.setRtnResponseMsg(rtnResponseMsg);
							mcfeRepaymentFlowDto.setPayType("1");
							mcfeRepaymentFlowDto.setTranctionDate(new Date());
							mcfeRepaymentFlowDto.setTransctionSeq(reqNo);
							flowDao.insertSelective(mcfeRepaymentFlowDto);
						}
					}

					// 更新代扣总记录
					McfePaymentWithholdDTO withholdDTOUpdate = new McfePaymentWithholdDTO();
					withholdDTOUpdate.setId(withholdDTO.getId());
					if (succcessAmount.compareTo(withholdAmount) == 0) {
						withholdDTOUpdate.setStatus("1");// 代扣成功
					} else {
						withholdDTOUpdate.setStatus("2");// 代扣处理中
					}
					withholdDTOUpdate.setTransctionSeq(reqNoBatch);
					withholdDTOUpdate.setWithholdCode(reqNoBatch);
					withholdDTOUpdate.setUpdatedBy("SYSTEM");
					withholdDTOUpdate.setUpdatedDate(new Date());
					withholdDTOUpdate.setAmountAct(succcessAmount);
					withholdDao.updateByPrimaryKeySelective(withholdDTOUpdate);
				}
			} catch (Exception e) {
				MarvelsLogUtil.getInstance().error(">>>>>loanId:" + loanId + ",自动代扣异常:", e);
			} finally {
				if (isNotLock) {// 如果是锁住的将所释放
					CacheUtils.del(key);
				}
			}
		}
	}
}
